/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package resmgmt

import (
	reqContext "context"
	"time"

	"git.cloud.inspur.com/ichain/ichain-protos-go/common"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/common/errors/retry"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/ichain/comm"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/providers/context"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/providers/ichain"
	"github.com/pkg/errors"
)

// WithTargets 指定节点
func WithTargets(targets ...ichain.Inode) RequestOption {
	return func(ctx context.Client, opts *requestOptions) error {
		for _, t := range targets {
			if t == nil {
				return errors.New("target is nil")
			}
		}

		opts.Targets = targets
		return nil
	}
}

// WithTargetEndpoints 指定节点地址
func WithTargetEndpoints(keys ...string) RequestOption {
	return func(ctx context.Client, opts *requestOptions) error {

		var targets []ichain.Inode

		for _, url := range keys {

			inodeCfg, err := comm.NetworkInodeConfig(ctx.EndpointConfig(), url)
			if err != nil {
				return err
			}

			inode, err := ctx.IChainProvider().CreateInodeFromConfig(inodeCfg)
			if err != nil {
				return errors.WithMessage(err, "creating inode from config failed")
			}

			targets = append(targets, inode)
		}

		return WithTargets(targets...)(ctx, opts)
	}
}

// WithTargetFilter 指定节点过滤
func WithTargetFilter(targetFilter ichain.TargetFilter) RequestOption {
	return func(ctx context.Client, opts *requestOptions) error {
		opts.TargetFilter = targetFilter
		return nil
	}
}

// WithTimeout 指定超时时间，如果没有指定则使用默认超时时间
func WithTimeout(timeoutType ichain.TimeoutType, timeout time.Duration) RequestOption {
	return func(ctx context.Client, o *requestOptions) error {
		if o.Timeouts == nil {
			o.Timeouts = make(map[ichain.TimeoutType]time.Duration)
		}
		o.Timeouts[timeoutType] = timeout
		return nil
	}
}

// WithConsenserEndpoint 指定共识节点地址
func WithConsenserEndpoint(key string) RequestOption {

	return func(ctx context.Client, opts *requestOptions) error {

		consenserCfg, found, ignoreConsenser := ctx.EndpointConfig().ConsenserConfig(key)
		if ignoreConsenser {
			return errors.Errorf("consenser url : %s is explicitly ignored by EntityMatchers config - can't add consenser", key)
		}

		if !found {
			return errors.Errorf("consenser not found for url : %s", key)
		}

		consenser, err := ctx.IChainProvider().CreateConsenserFromConfig(consenserCfg)
		if err != nil {
			return errors.WithMessage(err, "creating consenser from config failed")
		}

		return WithConsenser(consenser)(ctx, opts)
	}
}

// WithConsenser 指定共识节点对象
func WithConsenser(consenser ichain.Consenser) RequestOption {
	return func(ctx context.Client, opts *requestOptions) error {
		opts.Consenser = consenser
		return nil
	}
}

// WithConfigSignatures 指定签名
func WithConfigSignatures(signatures ...*common.ConfigSignature) RequestOption {
	return func(ctx context.Client, opts *requestOptions) error {
		opts.Signatures = signatures
		return nil
	}
}

// WithParentContext encapsulates grpc parent context.
func WithParentContext(parentContext reqContext.Context) RequestOption {
	return func(ctx context.Client, o *requestOptions) error {
		o.ParentContext = parentContext
		return nil
	}
}

// WithRetry 设置重传参数
func WithRetry(retryOpt retry.Opts) RequestOption {
	return func(ctx context.Client, o *requestOptions) error {
		o.Retry = retryOpt
		return nil
	}
}
